package org.zoomdy.gdbserver.extender;

import java.io.*;
import java.net.*;

public class Tail extends End
{
    public Tail()
    {
        _connectPort = 2331;
        _connectHost = "127.0.0.1";
        _tailThread = null;
    }
    
    public boolean start()
    {
        _startNoAckMode = false;
        
        if(!super.start())
        {
            return false;
        }
        
        try
        {
            if((this._clientSocket != null) && this._clientSocket.isConnected())
            {
                this._clientSocket.close();
            }
            
            if(this._tailThread != null)
            {
                this._tailThread.join();
                this._tailThread = null;
            }
            
            this._clientSocket = new Socket(this._connectHost, this._connectPort);
            this._inStream = this._clientSocket.getInputStream();
            this._outStream = this._clientSocket.getOutputStream();
        }
        catch(IOException e)
        {
            System.err.printf("连接 GDB Server：%s:%d 失败\n", this._connectHost, this._connectPort);
            return false;
        }
        catch(InterruptedException e)
        {
            e.printStackTrace();
            return false;
        }
        
        TailThread target = new TailThread();
        this._tailThread = new Thread(target);
        this._tailThread.start();
        
        return true;
    }
    
    public void stop()
    {
        try
        {
            // 关闭Socket，服务线程检测到Socket被关闭后，退出服务线程
            this._clientSocket.close();
        }
        catch(IOException e)
        {
            // TODO 需要更好的异常处理
            e.printStackTrace();
        }
        
        try
        {
            // 等待线程结束
            this._tailThread.wait();
        }
        catch(InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    
    public boolean setProperty(String name, String value)
    {
        if(name.equals("connectPort"))
        {
            int port = Integer.parseInt(value);
            if(port > 0)
            {
                this._connectPort = port;
                return true;
            }
        }
        else if(name.equals("connectHost"))
        {
            this._connectHost = value;
            return true;
        }
        
        return false;
    }
    
    public String getProperty(String name)
    {
        if(name == "connectPort")
        {
            return Integer.toString(this._connectPort);
        }
        else if(name == "connectHost")
        {
            return this._connectHost;
        }
        
        return null;
    }
    
    protected Packet getPacket()
    {
        Packet pkt = super.getPacket();
        if(pkt == null)
        {
            return pkt;
        }

        if(_startNoAckMode)
        {
            if(pkt.toString().equals("OK"))
            {
                this.setAckMode(false);
            }
            else
            {
                this.setAckMode(true);
            }
            _startNoAckMode = false;
        }
        
        return pkt;
    }
    
    protected boolean putPacket(Packet pkt)
    {
        if(pkt.startsWith("QStartNoAckMode"))
        {
            _startNoAckMode = true;
        }
        
        return super.putPacket(pkt);
    }
    
    public boolean inputCommand(Packet pkt)
    {
        return putPacket(pkt);
    }
    
    public boolean inputResponse(Packet pkt)
    {
        // Tail是最后一个节点，是产生响应的地方，不会有响应输入
        return false;
    }
    
    public boolean connect()
    {
        return this.start();
    }
    
    private void closeClient()
    {
        try
        {
            if(this._clientSocket != null)
            {
                this._clientSocket.close();
            }
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }
    
    private class TailThread implements Runnable
    {
        public void run()
        {
            // 连接服务循环
            while(!Tail.this._clientSocket.isClosed())
            {
                Packet pkt = Tail.this.getPacket();
                if(pkt == null)
                {
                    Tail.this.closeClient();
                    break;
                }
                
                boolean ret = Tail.this.outputResponse(pkt);
                if(!ret)
                {
                    Tail.this.closeClient();
                    break;
                }
            }
        }
    }
    
    private int _connectPort;
    private String _connectHost;
    private Thread _tailThread;
    private boolean _startNoAckMode;
}
